/**
 * 001 创建连接失败
 * 002 创建连接2失败
 * 003 创建连接3失败
 * 100 床在线，蓝牙连接成功
 * 101 床在线，蓝牙连接失败
 * 102 床不在线，蓝牙连接失败
 * 103 床不在线，蓝牙连接成功
 */
const app = getApp();
const utils = require('./util.js')
let code = null
let showLogs = true
let showLoadingFlag = false;
//延迟执行
function wait(seconds) {
    return new Promise(resolve => {
        setTimeout(resolve, seconds * 1000);
    });
}
//显示Loading
function myShowLoading(e) {
    showLoadingFlag = true;
    wx.showLoading({
        title: e,
        mask: true,
    })
}

//隐藏Loading
function myHideLoading(e) {
    wx.hideLoading({
        success: (res) => {},
    })
}

//提示框
function myShowToast(e) {
    if (showLoadingFlag == true) {
        myHideLoading();
    }
    wx.showToast({
        title: e,
        icon: 'none',
        duration: 2500
    });
}
//16进制字符串转ArrayBuffer
function hexStringToArrayBuffer(str) {
    let hex = str
    let typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
        return parseInt(h, 16)
    }))
    let buffer = typedArray.buffer
    return buffer;
}

// buffer转16进制
function ab2hex(buffer) {
    let hexArr = Array.prototype.map.call(
        new Uint8Array(buffer),
        function (bit) {
            return ('00' + bit.toString(16)).slice(-2)
        }
    )
    return hexArr.join('');
}



// 发送数据
async function sendMsg(msg, toArrayBuf = true) {
    let buf = toArrayBuf ? hexStringToArrayBuffer(msg) : msg;
    let bluetoothInfoTemp = wx.getStorageSync('bluetoothInfoTemp');
    return new Promise((resolve, reject) => {
        wx.writeBLECharacteristicValue({
            deviceId: bluetoothInfoTemp.deviceID,
            serviceId: bluetoothInfoTemp.servicesInfo.writeServiceID,
            characteristicId: bluetoothInfoTemp.characterInfo.writeCharactersID,
            value: buf,
            success: function (res) {
                console.log('发送成功====>', res)
                resolve(res);
            },
            fail: function (res) {
                console.log('发送失败====>', res)
            }
        })
    })
}

// 接受数据
function readMsg() {
    wx.onBLECharacteristicValueChange(function (res) {
        console.log('readMsg====>', res)
        var msg = ab2hex(res.value)
        console.log("接受的消息===》", msg)
    })
}


// 开启蓝牙适配器
function startBlueAdapter() {
    console.log('开启蓝牙适配器====>')
    if (!wx.openBluetoothAdapter) {
        return;
    }
    return new Promise((resolve, reject) => {
        wx.openBluetoothAdapter({
            success: res => {
                console.log("蓝牙适配器打开成功===>", res);
                resolve(true)
            },
            fail: res => {
                console.error("蓝牙适配器打开失败===>", res);
                resolve(false)
            }
        })
    })
}


let stopBluetoothTimeId;
//搜索设备
function startBluetoothDevicesDiscovery() {
    return new Promise((resolve, reject) => {
        // 搜不到5s自动关闭
        stopBluetoothTimeId = setTimeout(() => {
            stopBluetoothDevicesDiscovery();
            // utils.myShowToast('蓝牙连接失败', 1000)
        }, 10000);

        wx.startBluetoothDevicesDiscovery({
            services: [],
            success: function (res) {
                if (showLogs) {
                    console.log("success startBluetoothDevicesDiscovery:", res)
                }
                resolve(res);
            },
            fail: function (res) {
                if (showLogs) {
                    console.log("fail startBluetoothDevicesDiscovery:", res)
                }
                reject({})
            }
        })
    }).catch((res) => {

    })
}


// 获取mac地址
// device_id其实是mac地址（新的）
function getBluetoothDevices(bluetoothName) {
    console.log("搜索新设备bluetoothName===>", bluetoothName)
    return new Promise((resolve, reject) => {
        wx.getBluetoothDevices({
            success: (res) => {
                let devices = res.devices;
                if (showLogs) {
                    console.log("success getBluetoothDevices:", devices)
                }
                let device_id;
                for (let device of devices) {
                    if (device.name == bluetoothName || device.localName == bluetoothName) {
                        device_id = device.deviceId;
                        console.log("success bluetoothName:", bluetoothName)
                        console.log("success device.name:", device.name)
                        console.log("success localName:", device.localName)
                        console.log("success device_id:", device_id)
                        stopBluetoothDevicesDiscovery();
                        resolve(device_id);
                    }
                }
                if (!device_id) {
                    resolve();
                }
            },
        })
    }).catch((res) => {

    })
}

// 关闭蓝牙搜索
function stopBluetoothDevicesDiscovery() {
    wx.stopBluetoothDevicesDiscovery({
        success: (res) => {
            return code
            console.log('关闭蓝牙停止搜索成功');
        },
        fail: (res) => {
            console.log('关闭蓝牙停止搜索失败');
        },
    })
}


// 查找蓝牙设备(已经连接过的设备)
function onBluetoothDeviceFound(bluetoothName) {
    console.log("搜索已经连接过的设备bluetoothName===>", bluetoothName)
    return new Promise((resolve, reject) => {
        wx.onBluetoothDeviceFound(function (res) {
            let devices = res.devices;
            console.log('devices=====>', devices)
            if (showLogs) {
                console.log("success onBluetoothDeviceFound:", devices);
            }
            let device_id;
            for (let device of devices) {
                if (device.name == bluetoothName || device.localName == bluetoothName) {
                    let device_id = device.deviceId;
                    stopBluetoothDevicesDiscovery();
                    clearTimeout(stopBluetoothTimeId)
                    resolve(device_id);
                }
            }
            if (!device_id) {
                resolve();
            }
        });
    }).catch((res) => {
        stopBluetoothDevicesDiscovery();
        console.error("异常")
    })
}


function createBLEConnection(deviceID) {
    // wx.offBLEConnectionStateChange(listener)
    return new Promise((resolve, reject) => {
        wx.createBLEConnection({
            deviceId: deviceID,
            timeout: 10000,
            success: function (res) {
                // monitorIsBreak()
                if (showLogs) {
                    console.log("success createBLEConnection:", res);
                }
                resolve(res);
            },
            fail: function (res) {
                if (showLogs) {
                    console.log("fail createBLEConnection:", res);
                }
                // if (res.errCode == -1) {
                //     reject(res.errCode)
                // } else if (res.errCode == 10003) {
                //     reject(res.errCode)
                // } else {
                resolve(res);
                // }

            }
        })
    })
}

function getBLEDeviceServices(deviceID) {
    return new Promise((resolve, reject) => {
        wx.getBLEDeviceServices({
            deviceId: deviceID,
            success: function (res) {
                if (showLogs) {
                    console.log("success getBLEDeviceServices:", res);
                }
                resolve(res)
            },
            fail: function (res) {
                if (showLogs) {
                    console.log("fail getBLEDeviceServices:", res);
                }
                resolve();
            }
        })
    })
}

// 过滤需要的服务
function filterService(services) {
    return new Promise((resolve, reject) => {
        let servicesInfo = {};
        // 遍历过滤要的服务
        for (let service of services) {
            if (service.uuid.toUpperCase().indexOf("FFE0") != -1) {
                servicesInfo.readServiceID = service.uuid;
            } else if (service.uuid.toUpperCase().indexOf("FFE5") != -1) {
                servicesInfo.writeServiceID = service.uuid;
            } else if (service.uuid.toUpperCase().indexOf("D973") != -1) {
                servicesInfo.writeServiceID = service.uuid;
                servicesInfo.readServiceID = service.uuid;
            }
        }
        console.log("filter_servicesInfo===>", servicesInfo)
        // 没有的话，默认选择首个
        if (typeof servicesInfo.writeServiceID != undefined) {
            servicesInfo.writeServiceID = services[0].uuid;
        }
        if (typeof servicesInfo.readServiceID != undefined) {
            servicesInfo.readServiceID = services[0].uuid;
        }
        console.log("end_servicesInfo===>", servicesInfo)
        //完成标识
        if (typeof servicesInfo.readServiceID != undefined && typeof servicesInfo.readServiceID != undefined) {
            resolve(servicesInfo);
        } else {
            resolve();
        }
    })
}

function getDeviceCharacter(deviceID, serviceID) {
    return new Promise((resolve, reject) => {
        wx.getBLEDeviceCharacteristics({
            deviceId: deviceID,
            serviceId: serviceID,
            success: function (res) {
                if (showLogs) {
                    console.log("success getDeviceCharacter:", res);
                }
                resolve(res);
            },
            fail: function (res) {
                if (showLogs) {
                    console.log("fail getDeviceCharacter:", res);
                }
                resolve();
            }
        })
    })
}

function notifyBLECharacteristicValueChange(deviceID, serviceID, characteristicID) {
    return new Promise((resolve, reject) => {
        wx.notifyBLECharacteristicValueChange({
            state: true,
            deviceId: deviceID,
            serviceId: serviceID,
            characteristicId: characteristicID,
            success: function (res) {
                if (showLogs) {
                    console.log("success notifyBLECharacteristicValueChange:", res);
                }
                resolve(res);
            },
            fail: function (res) {
                if (showLogs) {
                    console.log("fail notifyBLECharacteristicValueChange:", res);
                }
                resolve();
            },
        })
    })
}

function closeBLEConnection(deviceID) {
    wx.offBLEConnectionStateChange(listener)
    return new Promise((resolve, reject) => {
        wx.closeBLEConnection({
            deviceId: deviceID,
            success: function (res) {
                if (showLogs) {
                    console.log("success closeBLEConnection:", res);
                }
                app.globalData.bluetooth_connected = false

                resolve(res);
            },
            fail: function (res) {
                if (showLogs) {
                    console.log("fail closeBLEConnection:", res);
                }
                resolve();
            }
        });
    })
}

function closeBluetoothAdapter() {
    return new Promise((resolve, reject) => {
        wx.closeBluetoothAdapter({
            success: function (res) {
                if (showLogs) {
                    console.log("success closeBluetoothAdapter:", res);
                }
                app.globalData.bluetooth_connected = false
                resolve(res);
            },
            fail: function (res) {
                if (showLogs) {
                    console.log("fail closeBluetoothAdapter:", res);
                }
                resolve();
            },
        })
    })
}
//监听器实体
let listener = async function (res) {
    console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`)
    if (!res.connected) { // 判断是否为断开连接
        wx.vibrateLong()
        // console.error("断开连接")
        // console.log('bluetoothInfo=======>', app.globalData.bluetoothInfo.deviceID)
        //关闭适配器释放资源
        // wx.closeBluetoothAdapter({
        //     success(res) {
        //         console.log('资源已释放')
        //     }
        // })
        if (app.globalData.bluetoothInfo) {
            if (res.deviceId == app.globalData.bluetoothInfo.deviceID) {
                app.globalData.failDevice = app.globalData.deviceId
                app.globalData.bluetooth_connected = false
                myShowLoading('蓝牙重连中')
                let code = await oneTouchConnectBluetooth(app.globalData.deviceId)
                errorHandle(code, false)
            }
        }
        if (app.globalData.bluetoothInfo2) {
            if (res.deviceId == app.globalData.bluetoothInfo2.deviceID) {
                app.globalData.failDevice2 = app.globalData.deviceId2
                app.globalData.bluetooth_connected2 = false
                myShowLoading('蓝牙重连中')
                let code = await oneTouchConnectBluetooth(app.globalData.deviceId2)
                if (app.globalData.bluetooth_connected == true) {
                    errorHandle(code, false)
                } else {
                    errorHandle(code, true)
                }

            }
        }

    } else {
        console.log("连接中")
        app.globalData.bluetooth_connected = true
    }
}
//查看蓝牙是否断开
function monitorIsBreak() { // 监听异常断开
    wx.onBLEConnectionStateChange(listener)
}



async function createBluetooth(deviceID) {
    console.log("createBluetooth===>")
    let createConnectionRes = await createBLEConnection(deviceID);
    console.log("createConnectionRes===>", createConnectionRes)
    if (!createConnectionRes || (createConnectionRes.errCode != 0 && createConnectionRes.errCode != -1)) {
        //app.globalData.deviceId = null
        console.log("连接失败，请重新扫码");
        let code = '001'
        return code;
    }
    //获取蓝牙的服务
    let getServiceRes = await getBLEDeviceServices(deviceID);
    console.log("getBLEDeviceServices", getServiceRes);
    if (!getServiceRes || getServiceRes.errCode != 0) {
        //app.globalData.deviceId = null
        console.log("连接失败，请重新扫码");
        let code = '002'
        return code;
    }
    //过滤出读写服务值
    let servicesInfo = await filterService(getServiceRes.services);
    console.log("filterService", servicesInfo);
    if (!servicesInfo) {
        //app.globalData.deviceId = null
        console.log("连接失败，请重新扫码");
        let code = '003'
        return code;
    }
    //获取写的特征值
    let writeCharacters = await getDeviceCharacter(deviceID, servicesInfo.writeServiceID);
    console.log("getDeviceCharacter write", writeCharacters);
    let writeCharactersID;
    if (writeCharacters && writeCharacters.errMsg == "getBLEDeviceCharacteristics:ok") {
        for (let character of writeCharacters.characteristics) {
            if (character.properties.write) {
                writeCharactersID = character.uuid;
                break;
            }
        }
    }
    console.log("write character", writeCharactersID);
    if (!writeCharactersID) {
        //app.globalData.deviceId = null
        console.log("连接失败，请重新扫码");
        let code = '004'
        return code;
    }
    //获取读的特征值
    let readCharacters = await getDeviceCharacter(deviceID, servicesInfo.readServiceID);
    console.log("getDeviceCharacter read", readCharacters);
    let readCharactersID;
    if (readCharacters && readCharacters.errMsg == "getBLEDeviceCharacteristics:ok") {
        for (let character of readCharacters.characteristics) {
            if (character.properties.notify) {
                readCharactersID = character.uuid;
                break;
            }
        }
    }
    console.log("read character", readCharactersID);
    if (!readCharactersID) {
        //app.globalData.deviceId = null
        console.log("连接失败，请重新扫码");
        let code = '005'
        return code;
    }
    let characterInfo = {
        writeCharactersID: writeCharactersID,
        readCharactersID: readCharactersID
    };
    console.log("characterInfo===>", characterInfo)

    let bluetoothInfoTemp = {
        deviceID: deviceID,
        servicesInfo: servicesInfo,
        characterInfo: characterInfo,
    }
    console.log("bluetoothInfoTemp===>", bluetoothInfoTemp)
    wx.setStorageSync('bluetoothInfoTemp', bluetoothInfoTemp)
    let notifyChangeRes = await notifyBLECharacteristicValueChange(deviceID, servicesInfo.readServiceID, readCharactersID);
    console.log("notifyBLECharacteristicValueChange", notifyChangeRes);
    if (!notifyChangeRes || notifyChangeRes.errCode != 0) {
        //app.globalData.deviceId = null
        console.log("连接失败，请重新扫码");
        let code = '006'
        return code;
    }
    clearTimeout(stopBluetoothTimeId)
    if (app.globalData.bluetoothInfo == null) {
        app.globalData.bluetoothInfo = bluetoothInfoTemp
    } else {
        app.globalData.bluetoothInfo2 = bluetoothInfoTemp
    }
    if (app.globalData.bluetooth_connected == true) {
        app.globalData.bluetooth_connected2 = true
    } else {
        app.globalData.bluetooth_connected = true
    }
    app.globalData.dataswitch = true
    let nowTime = new Date().getTime() //获取当前毫秒数
    let standardTime = wx.getStorageSync('subcribe') == '' ? 0 : parseInt(wx.getStorageSync('subcribe')) //订阅期限毫秒数
    console.log('standardTime====>', standardTime, wx.getStorageSync('subcribe'))
    if (standardTime < nowTime) {
        app.globalData.needsubscribe = true
    } else {
        app.globalData.needsubscribe = false
    }
    return '000'
    // myShowToast('设备已连接')
}



async function oneTouchConnectBluetooth(bluetoothname, showLoading = false) {
    //已经连接或者没有绑定设备号
    // if (app.globalData.bluetooth_connected || bluetoothname.length == 0) {
    //     console.log("bluetoothname===>", bluetoothname)
    //     console.log("蓝牙状态===>", app.globalData.bluetooth_connected, "是否有设备连接===>", !bluetoothname.length == 0)
    //     return
    // }
    wx.offBLEConnectionStateChange(listener)
    monitorIsBreak()
    // 开启蓝牙适配器
    console.log("连接蓝牙目标===>", bluetoothname)
    let hasStartBlueAdapter = await startBlueAdapter()
    if (!hasStartBlueAdapter) {
        // utils.myShowToast('请打开手机蓝牙')
        console.error('手机蓝牙适配器不可用，请重新连接====>')
        return 500
    }
    console.log("检测小程序是否具备蓝牙权限")

    // 检测小程序是否具备蓝牙权限
    let hasBuletoothPermission = await getBuletoothPermission()
    if (!hasBuletoothPermission) {
        // utils.myShowToast('检测小程序是否具备蓝牙权限，\n网络状况是否良好')
        return 501
    }
    // 搜索附件的设备
    await startBluetoothDevicesDiscovery().then(res => {
        console.log('Discovery=====>', res)
    })
    console.log('startBluetoothDevicesDiscovery')
    //延迟1.5s后执行下面的内容
    await wait(1.5)
    // 连接指定设备，返回mac地址（新设备）
    let deviceID = await getBluetoothDevices(bluetoothname);
    if (!deviceID) {
        // 监听寻找到新设备的事件
        deviceID = await onBluetoothDeviceFound(bluetoothname);
    }

    console.log("是否存在找到设备==>", deviceID);
    // 连接存在设备
    if (deviceID) {
        console.log("连接存在设备")
        let code = await createBluetooth(deviceID)
        if (code != '000') {
            deviceID = undefined
        }
    }
    if (!showLoading) {
        clearTimeout(stopBluetoothTimeId)
    }
    let code = 0
    if (showLoadingFlag == true) {
        if (!deviceID) {
            myHideLoading()
            console.log('error=====>未搜索到设备', app.globalData.bedInfo, app.globalData.stateInfo)
            app.globalData.bedInfo.forEach((item, index) => {
                console.log(item, index, bluetoothname)
                if (item == bluetoothname) {
                    // if (app.globalData.stateInfo[index] == true) {
                    code = 101 //床在线，蓝牙连接失败
                    console.log('101-床在线，蓝牙连接失败')
                    // } 
                    // else {
                    //     if (app.globalData.bluetooth_connected == true && app.globalData.deviceId2 != null) {
                    //         code = 105 //一人睡双床时一张床离线另一张正常
                    //         console.log('105-一人睡双床时一张床离线另一张正常')
                    //     } else {
                    //         code = 102 //床不在线，蓝牙连接失败
                    //         console.log('102-床不在线，蓝牙连接失败')
                    //     }
                    // }
                }
            })
            // console.log('code', code)
        } else {
            //蓝牙意外断开的重连，根据connect_code值判断
            myHideLoading()
            console.log('success=====>连接成功', app.globalData.bedInfo, app.globalData.stateInfo)
            app.globalData.bedInfo.forEach((item, index) => {
                console.log('match====>', item, index)
                if (item == bluetoothname) {
                    // if (app.globalData.stateInfo[index] == true) {
                    code = 100 //床在线，蓝牙连接成功
                    console.log('100-床在线，蓝牙连接成功')
                    // monitorIsBreak()
                    // } 
                    // else {
                    //     code = 103 //床不在线，蓝牙连接成功
                    //     console.log('103-床不在线，蓝牙连接成功')
                    // }
                }
            })

        }
        return code
    }
}



// 获取蓝牙权限
function getBuletoothPermission() {
    return new Promise((resolve, reject) => {
        wx.getSetting({
            success: res => {
                console.log("获取设置信息===》", res)
                // 位置权限没有或者拒绝
                if (typeof (res.authSetting['scope.bluetooth']) != undefined && !res.authSetting['scope.bluetooth']) {
                    wx.getSetting({
                        success(res) {
                            if (!res.authSetting['scope.bluetooth']) {
                                wx.authorize({
                                    scope: 'scope.bluetooth',
                                    success() {
                                        console.log("同意蓝牙")
                                        resolve(true);
                                    },
                                    fail() {
                                        resolve(false);
                                    }
                                })
                            }
                        }
                    })
                } else {
                    // app.globalData.bluetooth = true
                    console.log("蓝牙有权限")
                    resolve(true);
                }
            },
            fail: res => {
                console.log("获取蓝牙权限失败")
                resolve(false);
            }
        })
    })

}


//重连code码处理
async function errorHandle(code, flag) {
    flag = flag || false
    console.log('flag', flag)
    console.log('code:', code)
    let pages = getCurrentPages()
    let prevPage = null
    if (pages.length > 0) {
        prevPage = pages[pages.length - 1]
    }
    if (code == 100) { //床在线，蓝牙连接成功
        console.log('连接正常')
    } else if (code == 101) { //床在线，蓝牙连接失败
        let my_code = 101
        console.log('其他原因')
        if (flag) { //已在连接页面
            my_code = 1011
            return my_code
        } else {
            if (prevPage.route === 'pages/index/index' || prevPage.route === 'pages/profile/profile') {
                wx.navigateTo({
                    url: '/pages/connect/bedside/bedside?stage=3',
                })
            } else {
                wx.redirectTo({
                    url: '/pages/connect/bedside/bedside?stage=3',
                })
            }
        }
    } else if (code == 102) { //床不在线，蓝牙连接失败
        console.log('设备断电')
        let my_code = 102
        if (flag) {
            my_code = 1021
            return my_code
        } else {
            if (prevPage.route === 'pages/index/index' || prevPage.route === 'pages/profile/profile') {
                wx.navigateTo({
                    url: '/pages/connect/bedside/bedside?stage=3',
                })
            } else {
                wx.redirectTo({
                    url: '/pages/connect/bedside/bedside?stage=3',
                })
            }
        }
    } else if (code == 103) { //床不在线，蓝牙连接成功
        myShowToast('网络异常，请联系酒店前台')
        app.globalData.deviceId = null
        app.globalData.deviceId2 = null
        app.globalData.bluetoothInfo = null
        app.globalData.bluetoothInfo2 = null
        console.log('设备未联网')
        return
    } else if (code == 105) {
        myShowToast('设备异常，请联系酒店前台')
        app.globalData.deviceId = null
        app.globalData.deviceId2 = null
        app.globalData.bluetoothInfo = null
        app.globalData.bluetoothInfo2 = null
        console.log('一人睡双床一侧设备离线另一侧正常')
        return
    } else if (code == 500) {
        myShowToast('蓝牙已关闭，请重新连接')
        app.globalData.deviceId = null
        app.globalData.deviceId2 = null
        app.globalData.bluetoothInfo = null
        app.globalData.bluetoothInfo2 = null
        if (prevPage.route !== 'pages/index/index') {
            wx.switchTab({
                url: '/pages/index/index',
            })
        }
        return
    } else if (code == 501) {
        myShowToast('蓝牙权限未开启，请先开启')
        app.globalData.deviceId = null
        app.globalData.deviceId2 = null
        app.globalData.bluetoothInfo = null
        app.globalData.bluetoothInfo2 = null
        if (prevPage.route !== 'pages/index/index') {
            wx.switchTab({
                url: '/pages/index/index',
            })
        }
        return
    } else {
        console.log('未知错误')
        // myShowToast('未知错误，请重新扫码连接')
        // app.globalData.deviceId = null
        // app.globalData.deviceId2 = null
        // app.globalData.bluetoothInfo = null
        // app.globalData.bluetoothInfo2 = null
        return
    }
}


module.exports = {
    startBlueAdapter,
    sendMsg,
    readMsg,
    startBluetoothDevicesDiscovery,
    getBluetoothDevices,
    onBluetoothDeviceFound,
    stopBluetoothDevicesDiscovery,
    createBLEConnection,
    getBLEDeviceServices,
    filterService,
    getDeviceCharacter,
    notifyBLECharacteristicValueChange,
    closeBLEConnection,
    closeBluetoothAdapter,
    createBluetooth,
    oneTouchConnectBluetooth,
    ab2hex,
    myShowLoading,
    myHideLoading,
    myShowToast,
    errorHandle,
    wait
}